#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <functional>

#include "mutex.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"
#include "log.hpp"
#include "threadpool.hpp"

#define BACKLOG 8

namespace TcpServerModule
{
    using namespace LockModule;
    using namespace LogModule;
    using namespace ThreadPoolModule;
    static const uint16_t gport = 8080;
    using handler_t = std::function<std::string(std::string)>;
    using addu_t = std::function<void(int,const InetAddr &)>;
    using removeu_t = std::function<void(const InetAddr &)>;
    using route_t = std::function<void(const std::string&)>;

    class TcpServer
    {
    public:
        TcpServer(handler_t handler ,int port = gport)
            : _handler(handler), _port(port), _isrunning(false)
        {
        }
        void InitServer()
        {
            // socket
            _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensockfd < 0)
            {
                LOG(FATAL) << "socket failed";
                Die(SOCKET_ERR);
            }
            LOG(INFO) << "socket success,sockfd is: " << _listensockfd;
            struct sockaddr_in local;
            bzero(&local, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = ::htons(gport);
            local.sin_addr.s_addr = INADDR_ANY;

            // bind
            int n = ::bind(_listensockfd, CONV(&local), sizeof(local));
            if (n < 0)
            {
                LOG(FATAL) << "bind failed";
                Die(BIND_ERR);
            }
            LOG(INFO) << "bind success,sockfd is: " << _listensockfd;

            n = ::listen(_listensockfd, BACKLOG);
            if (n < 0)
            {
                LOG(FATAL) << "listen failed";
                Die(LISTEN_ERR);
            }
            LOG(INFO) << "listen success,sockfd is: " << _listensockfd;
        }
        void RegisterService(addu_t adduser, route_t route, removeu_t removeuser)
        {
            _addu = adduser;
            _route = route;
            _removeu = removeuser;
        }

        // 处理任务
        void HandlerRequest(int sockfd)
        {
            LOG(INFO) << "deal HandlerRequest,sockfd is " << sockfd;
            char inbuffer[4096];
            while (true)
            {
                ssize_t n = ::recv(sockfd, inbuffer, sizeof(inbuffer) - 1, 0);
                if (n > 0)
                {
                    inbuffer[n] = 0;
                    LOG(INFO) << inbuffer;
                    // std::string echo_str = "server echo# ";
                    // echo_str += inbuffer;
                    // ::send(sockfd, echo_str.c_str(), echo_str.size(), 0);
                    //handler_t();
                    _route(inbuffer);
                }
                else if (n == 0)
                {
                    LOG(INFO) << "client quit";
                    //移除用户
                    break;
                }
                else
                {
                    LOG(ERROR) << "recv失败,线程退出";
                    break;
                }
            }
        }
        void Start()
        {
            _isrunning = true;
            while (_isrunning)
            {
                // 获取链接
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);

                int sockfd = ::accept(_listensockfd, CONV(&peer), &len);
                if (sockfd < 0)
                {
                    LOG(WARNING) << "accept error";
                    continue;
                }
                LOG(INFO) << "accept success,socket is: " << sockfd;
                InetAddr addr(peer);
                LOG(INFO) << "client: " << addr.Addr();
                //添加用户
                _addu(sockfd,addr);
                // 发送任务
                // 1.多进程
                //  pid_t pid = fork();
                //  if(pid == 0)
                //  {
                //      if(fork()>0)
                //          exit(0);//孙子进程->孤儿进程 相当于分离
                //      HandlerRequest(sockfd);
                //      exit(0);
                //  }
                //  waitpid(pid,nullptr,0);
                //  ::close(sockfd);

                // 2.多线程 - 线程池
                ThreadPool<std::function<void(std::string)>>::GetInstance()->Enqueue([this, sockfd,addr](std::string name)
                                                                                     {LOG(INFO)<<name<<": 开始处理 HandlerRequest";
                                                                                this->HandlerRequest(sockfd);
                                                                                this->remove(addr); });
            }
        }
        void Stop()
        {
            _isrunning = false;
        }
        ~TcpServer()
        {
        }

        void remove(const InetAddr& id)
        {
            _removeu(id);
        }
    private:
        int _listensockfd; // 监听套接字
        uint16_t _port;
        bool _isrunning;
        handler_t _handler;

        addu_t _addu;
        removeu_t _removeu;
        route_t _route;
    };
}